package main

import (
	"fmt"
)

var a = 1
var b = 0

func main() {
	passByVal(a) //值传递

	fmt.Printf("pass by val: a=%v", a)
	passByRef(&a)
	fmt.Printf("\npass by Ref: a=%v", a)
	/*
	   运行结果：
	   pass by val: 1
	   pass by Ref: 2
	*/

	swapVal(a, b)
	fmt.Printf("\nswap by Val: a=%v, b=%v,", a, b)
	swapRef(&a, &b)
	fmt.Printf("\nswap by Ref: a=%v, b=%v", a, b)

	/*
	   运行结果：
	   swap by Val: a=2, b=0,
	   swap by Ref: a=0, b=2
	*/

	a, b = swap(a, b)
	fmt.Printf("\na=%v, b=%v", a, b)

	xiaoming := student{
		"xiaoming",
		12,
	}

	fmt.Printf("\nbefore setting, %s's age is %d\n", xiaoming.name, xiaoming.age)

	// 和java不同，对象的方法不能改变值，传指针可以改变值
	xiaoming.setAgeByValue(13)
	fmt.Printf("after setting value to 13, %s's age is %d\n", xiaoming.name, xiaoming.age)

	// 一个method的receiver是*T,你可以在一个T类型的实例变量V上面调用这个method，而不需要&V去调用这个method
	xiaoming.setAgeByRef(14)
	fmt.Printf("after setting ref to 14, %s's age is %d\n", xiaoming.name, xiaoming.age)
	/**

	before setting, xiaoming's age is 12
	after setting value to 13, xiaoming's age is 12
	after setting ref to 14, xiaoming's age is 14

	*/

}

type student struct {
	name string
	age  int
}

func (s *student) setAgeByRef(age int) {
	s.age = age
}

func (s student) setAgeByValue(age int) {
	s.age = age
}

//更合理的交换
func swap(a, b int) (int, int) {
	return b, a
}

//更合理的

func swapVal(a, b int) { //传值交换，调用无效
	b, a = a, b
}

func swapRef(a, b *int) { //指针传递，值被交换
	*b, *a = *a, *b
}

func passByRef(a *int) {
	*a++
}

func passByVal(a int) {
	a++
}
